#light

namespace Modelica.CoreLite

    open System 
    open OmcSocketClient
    open Modelica.ModelicaTypes
    open Modelica.Annotations
    open Modelica.Parsers
    open System.Windows
    open System.Globalization
    open System.Windows.Media

    // TODO: Vytvorit nejaky korenovu strukturu, az nie su top level elementy len tak v nejakom List<> a domysliet, ako sa s nou bude pracovat v celom programe
    // TODO: F# list vs. C# list
    // TODO: ZOPTIMALIZOVATTTTTTTT lebo je to hovacky pomale - mozno netahat pre vsetko ikony a diagramy, zistit, ci ich mozu mat aj funckie, bloky etc.
    // TODO: Kontrolovat navratove hodnoty omc funkcii, ked pride nejaka chyba vyhodit vynimku
    // F# stuff
    // TODO: Pada to v release mode na nezachytenej vynimke pri volani AnnotationParser.ParseIconAnnotation, 
    // ktora sa ale zachytava, ked nie je zaskrtnute v properties projektu "Generate debugging info" -> co s tym? -> Tomas Petricek
    // TODO: Nutne referencovat dll-ka .NETu 3.5 rucne -> Tomas Petricek
    // TODO: Custom build vo VS 2008 nejde... 
    // TODO: zamenit map za iter
    // TODO: pozor na default hodnoty anotacii, hlavne transform
    // TODO: Handlovanie chyb z omc (momentalne hlavne v createModelicaClass)
    // TODO: Ked je anotacia ikony len extent, tak to nechodi...
    
    // HACK ->1: neviem ako spravit len deklaraciu typu, aby som mohol referencovat triedy jednu z druhej

    ///<summary>
    /// Class encapsulating basic methods for creating abstract model structure,
    /// concept for the actual CORE that will be implemented later</summary>       
    type Core =
        {
            AbstractModel:List<ModelicaClass>            
        }
                            
        /// <summary>
        /// Loads model from file specified </summary>
        /// <param name="fileName">
        /// Path to the file with model, uses forward slashes, NOT backslashes </param>
        /// <returns> Boolean value indicating whether the model was succesfully loaded or not. </returns>
        static member LoadModel(fileName:string,relativeDirectory:string) =            
            let succes = omc.LoadFile(fileName,relativeDirectory)
            succes
        
        /// <summary>
        /// Gets all ancestors of the class and adds them to the list of base classes. When needed, base class is
        /// is also obtained from the omc. </summary>
        /// <param name="mdClass">
        /// Modelica class ancestors of which should be retrieved. </param>        
        static member private getAncestors(mdClass:ModelicaClass) =
            // get the number of classes the class derives from
            let inheritanceCount = omc.GetInheritanceCount(mdClass.QualifiedName)
            // get all the classes and create their representation
            for n = 1 to inheritanceCount do
                let nthBaseClassName = omc.GetNthInheritedClass(mdClass.QualifiedName,n).Trim([|'\r';'\n'|])
                let nthBaseClass = Core.createModelicaClass(nthBaseClassName)
                mdClass.BaseClasses.Add(nthBaseClass)
        
        /// <summary>
        /// Creates representation of Modelica type specified in parameter. Decides whether it's one of the pritive ones
        /// or the type is class. </summary>
        /// <param name="typeName">
        /// Name of the modelica type </param>        
        /// <returns> Representation of Modelica type - type IModelicaTypeSystemBase </returns>
        static member private createModelicaType(typeName:string) = 
            match typeName with
                | "Boolean" -> new ModelicaBoolean() :> IModelicaTypeSystemBase
                | "Integer" -> new ModelicaInteger() :> IModelicaTypeSystemBase
                | "Real" -> new ModelicaReal() :> IModelicaTypeSystemBase
                | "String" -> new ModelicaString() :> IModelicaTypeSystemBase
                | "enumeration" -> new ModelicaEnum() :> IModelicaTypeSystemBase
                | _ -> Core.createModelicaClass(typeName) :> IModelicaTypeSystemBase
                
        /// <summary>
        /// Creates Transformation object for the diagr from string list obtained from omc. </summary>
        /// <param name="transList">
        /// List of strings with parameters of transformation obtained from omc </param>        
        /// <returns> Created Transformation object. </returns>
        static member private createDiagramTransformation(transList:string[]) = 
            let x = Double.Parse(transList.[1],new CultureInfo(""))
            let y = Double.Parse(transList.[2],new CultureInfo(""))
            let origin = new Point(x,y)            
            let scale = Double.Parse(transList.[3],new CultureInfo(""))
            let aspectRatio = Double.Parse(transList.[4],new CultureInfo(""))
            let flipHorizontal = Boolean.Parse(transList.[5])
            let flipVertical =  Boolean.Parse(transList.[5])
            let rotation = Double.Parse(transList.[7],new CultureInfo(""))
            new Transformation(origin,scale,aspectRatio,flipHorizontal,flipVertical,rotation)
        
        /// <summary>
        /// Creates Transformation object for the icon  from string list obtained from omc. </summary>
        /// <param name="transList">
        /// List of strings with parameters of transformation obtained from omc </param>        
        /// <returns> Created Transformation object. </returns>
        static member private createIconTransformation(transList:string[]) = 
            let x = Double.Parse(transList.[8],new CultureInfo(""))
            let y = Double.Parse(transList.[9],new CultureInfo(""))
            let origin = new Point(x,y)            
            let scale = Double.Parse(transList.[10],new CultureInfo(""))
            let aspectRatio = Double.Parse(transList.[11],new CultureInfo(""))
            let flipHorizontal = Boolean.Parse(transList.[12])
            let flipVertical =  Boolean.Parse(transList.[13])
            let rotation = Double.Parse(transList.[14],new CultureInfo(""))
            new Transformation(origin,scale,aspectRatio,flipHorizontal,flipVertical,rotation)
        
        /// <summary>
        /// Gets placement for the specified component.
        /// <param name="mdClass">
        /// ModelicaClass whose n-th component should be obtained. </param>
        /// <param name="compNumber">
        /// Number of the component </param>        
        /// <returns> Placement object or null when component has no placement. </returns>
        static member private getComponentPlacement(mdClass:ModelicaClass, compNumber:int) = 
            let placementAnnotation = omc.GetNthComponentAnnotation(mdClass.QualifiedName,compNumber)
            let parsedAnnotation = placementAnnotation.Trim([|'{';'}';'\r';'\n'|]) |> String.split([',']) |> List.to_array
            match parsedAnnotation.Length with
                | 0 -> null
                | _ -> 
                    let visible = Boolean.Parse(parsedAnnotation.[0])
                    let diagramTrans = Core.createDiagramTransformation(parsedAnnotation)
                    let iconTrans = Core.createIconTransformation(parsedAnnotation)
                    new Placement(visible,diagramTrans,iconTrans)
                    
        // <summary>
        /// Gets all component of the modelica class.
        /// <param name="mdClass">
        /// ModelicaClass whose components should be obtained. </param>                
        static member private getComponents(mdClass:ModelicaClass) = 
            let componentCount = omc.GetComponentCount(mdClass.QualifiedName)
            for n = 1 to componentCount do
                let compInfo = omc.GetNthComponent(mdClass.QualifiedName,n) |> String.trim(['{';'}';'\r';'\n']) |> String.split([',']) |> List.to_array
                let componentType = Core.createModelicaType(compInfo.[0])
                let place = Core.getComponentPlacement(mdClass,n)
                let classComponent = new Component(componentType,compInfo.[1],compInfo.[2].Trim([|'"'|]),place)
                classComponent.ContainerClass <- mdClass
                mdClass.Components.Add(classComponent)
        
        /// <summary>
        /// Creates modelica element corresponding to its actual type. The descendants of the
        /// element are NOT retrieved. </summary>
        /// <param name="className">
        /// Qualified name of the element, that will be constructed </param>
        static member private createModelicaClass(typeName:string):ModelicaClass =
            match ClassRegister.ClassWasCreated(typeName) with
                | false ->
                    try
                        let classInfo:string = omc.GetClassInformation(typeName)
                        let classInformation = classInfo.Trim([|'{';'}';'\r';'\n'|]) |> String.split([',']) |> List.to_array
                        let iconAnnotation:string = omc.GetIconAnnotation(typeName)
                        let mutable icon = null
                        try
                            icon <- AnnotationParser.ParseIconAnnotation(iconAnnotation)            
                        with e ->
                            icon <- new Icon()                           
                        let createdClass =
                            match classInformation.[0].Trim([|'\r';'\n';'"'|]) with                
                                | "package" -> new ModelicaPackage(typeName,new Diagram(),icon) :> ModelicaClass
                                | "model" -> new ModelicaModel(typeName,new Diagram(),icon)  :> ModelicaClass
                                | "record" -> new ModelicaRecord(typeName,new Diagram(),icon)  :> ModelicaClass     
                                | "connector" -> new ModelicaConnector(typeName,new Diagram(),icon)  :> ModelicaClass         
                                | "type" -> new ModelicaType(typeName,new Diagram(),icon)  :> ModelicaClass
                                | "block" -> new ModelicaBlock(typeName,new Diagram(),icon)  :> ModelicaClass
                                | "function" -> new ModelicaFunction(typeName,new Diagram(),icon)  :> ModelicaClass
                                | "class" -> new ModelicaClass(typeName,new Diagram(),icon  )                                                                                    
                                | _ -> raise (Exception("Unknown class type"))
                        createdClass.HelpString <- classInformation.[1].Trim([|'"'|])
                        Core.getAncestors(createdClass)
                        Core.getComponents(createdClass)
                        ClassRegister.AddCreatedClass(createdClass)
                        createdClass
                    with e ->
                        let createdClass = new ModelicaClass(typeName,new Diagram(),new Icon() )
                        ClassRegister.AddCreatedClass(createdClass)
                        createdClass
                | true -> ClassRegister.GetCreatedClass(typeName)
            
        
        /// <summary>
        /// Gets all the root elements of Modelica model structure </summary>
        /// <returns>
        /// List of ModelicaClasses which are root elements of the Modelica Model structure </returns> 
        static member GetRootClasses() =            
            let topClasses = omc.GetClassNames()
            let trimmed  =  topClasses.Trim([|'{';'}';'\n';'\r'|]) |> String.split([','])
            trimmed |> List.map Core.createModelicaClass |> ResizeArray.of_list
        
        /// <summary>
        /// Creates list of non-qualified names (strings) of the child elements of class specified in parameter </summary>
        /// <param name="rootClass">
        /// Class whose child elements will be returned </param>
        /// <returns>
        /// List of names of child elements </returns>
        static member private getContainedClassesStringList(rootClass:ModelicaClass) =
            let topClasses = omc.GetClassNames(rootClass.QualifiedName)
            topClasses.Trim([|'{';'}';'\r';'\n'|])  |> String.split [','] |> List.map (fun (a:string) -> rootClass.QualifiedName + "." + a)
        
        /// <summary>
        /// Creates list of non-qualified names (strings) of the root elements of Modelica model structure </summary>        
        /// <returns>
        /// List of names of root elements </returns>
        static member private getRootClassesStringList() =
            let topClasses = omc.GetClassNames()
            let trimmed  =  topClasses.Trim([|'{';'}';'\n';'\r'|]) |> String.split([','])
            trimmed
            
        /// <summary>
        /// Creates next level of model structure with root in class specified in parameter.
        /// Fills property ContainedClasses with child class of the rootClass.
        ///  </summary>
        /// <param name="rootClass"> 
        /// Class whose content will be examined for child elements </param>
        /// <returns> 
        /// rootClass with filled ContainedClasses property </returns>
        static member GetModelNextLevel(rootClass:ModelicaClass) =
            let classes = Core.getContainedClassesStringList(rootClass)
            let contClasses = classes |>  List.map Core.createModelicaClass
            rootClass.ContainedClasses <- ResizeArray.of_list contClasses;
            rootClass

        /// <summary>
        /// Creates whole branch of model structure with root in class specified in parameter.
        /// Fills property ContainedClasses with child class of the rootClass.
        ///  </summary>
        /// <param name="rootClass"> 
        /// Root class of the branch of the model structure </param>
        /// <returns> 
        /// rootClass with filled ContainedClasses property </returns>
        static member GetModelBranch(rootClass:ModelicaClass) =
            Core.GetModelNextLevel(rootClass)
            rootClass.ContainedClasses |> ResizeArray.map (Core.GetModelBranch)
            rootClass

        /// <summary>
        /// Creates in-memory structure of model consisting of elements of modelica source code,
        /// which represented using types derived from ModeliceTypes (see file modelicatypes.fs) </summary>
        /// <returns>
        /// List of ModelicaClass types, which consists of top-level elements in currently loaded models </returns>
        static member GetModelStructure() =  
            let rootClasses = Core.GetRootClasses()
            rootClasses |> ResizeArray.map Core.GetModelBranch
            rootClasses
        
        /// <summary>
        /// Creates string representaion of the Transformation object in a way omc expects it. </summary>
         /// <param name="trans"> 
        /// Transformation object which will be represented as a string. </param>
        /// <returns>
        /// String representation of Transformation object. </returns>
        static member private createTransformationString(trans:Transformation) =
            "transformation(x=" + trans.Origin.X.ToString(new CultureInfo("")) + ",y=" + trans.Origin.X.ToString(new CultureInfo("")) + ",scale=" + 
                trans.Scale.ToString(new CultureInfo("")) + ",aspectRatio=" + trans.AspectRatio.ToString(new CultureInfo("")) + ",flipHorizontal=" +
                trans.FlipHorizontal.ToString().ToLower() + ",flipVertical=" + trans.FlipVertical.ToString().ToLower() + ",rotation=" +
                trans.Rotation.ToString(new CultureInfo("")) + ")"
        
        /// <summary>
        /// Updates placement of the coponent in the omc </summary>
        /// <param name="comp"> 
        /// Component whose placement should be updated. </param>        
        static member private updateComponentPlacement(comp:Component) = 
            match comp.Placement with 
                | null -> ""
                | _ ->
                    let iconStr = "iconTransformation=" + Core.createTransformationString(comp.Placement.IconTransformation)
                    let diagStr = "transformation=" + Core.createTransformationString(comp.Placement.Transformation)
                    let visible = "visible=" + comp.Placement.Visible.ToString().ToLower()
                    let annotationStr = "annotate=Placement( " + visible + "," + diagStr + "," + iconStr + ")"
                    let updateStr = comp.Name + "," + comp.Type.ToString + "," + comp.ContainerClass.ToString() + "," + annotationStr
                    omc.UpdateComponent(updateStr)
                    
        /// <summary>
        /// Creates string representaion of the array Point objects in a way omc expects it. </summary>
        /// <param name="points"> 
        /// Array of Point objects which will be represented as a string. </param>
        /// <returns>
        /// String representation of array of Point objects. </returns>
        static member private pointsToString(points : Point[]) =
            let mutable pointsStr = "points={"
            for i = 0 to points.Length-1 do
                pointsStr <- pointsStr + "{" + points.[i].X.ToString(new CultureInfo("")) + "," + points.[i].X.ToString(new CultureInfo("")) + "},"
            pointsStr.TrimEnd([|','|]) + "}"
            
        /// <summary>
        /// Creates string representaion of the Arrow enumeration in a way omc expects it. </summary>
        /// <param name="arrow"> 
        /// Arrow enumeration value which will be represented as a string. </param>
        /// <returns>
        /// String representation of Arrow enumeration value. </returns>
        static member private getArrowStr(arrow: Arrow[]) = 
            let mutable arrowStr = "arrow={"
            for i = 0 to arrow.Length-1 do
                arrowStr <- arrowStr + "Arrow." + arrow.[i].ToString() + ","
            arrowStr.TrimEnd([|','|]) + "}"
        
        /// <summary>
        /// Creates string representaion of the Smooth enumeration in a way omc expects it.
        /// Current version of the omc supports just boolean values, so the enumeration is mapped to true/false. </summary>
        /// <param name="sm"> 
        /// Smooth enumeration value which will be represented as a string. </param>
        /// <returns>
        /// String representation of Smooth enumeration value. </returns>
        static member private getSmoothStr(sm: Smooth) = 
            match sm with
                | Smooth.Bezier -> "smooth=true"
                | Smooth.None -> "smooth=false"
                | _ -> "smooth=false"
                
        /// <summary>
        /// Creates string representaion of the Color object in a way omc expects it. </summary>
        /// <param name="col"> 
        /// Color object which will be represented as a string. </param>
        /// <returns>
        /// String representation of Color object. </returns>
        static member private getColorStr(col:Color) = 
            "{" + col.R.ToString(new CultureInfo("")) + "," + col.G.ToString(new CultureInfo("")) + "," + col.B.ToString(new CultureInfo("")) + "}"

        /// <summary>
        /// Creates string representaion of the TestStyle enumeration array in a way omc expects it.
        /// Current version of the omc does not support this feature. </summary>
        /// <param name="txtStyle"> 
        /// TextStyle enumeration array which will be represented as a string. </param>
        /// <returns>
        /// String representation of TextStyle enumeration array. </returns>
        static member private getTextStyleStr(txtStyle:ResizeArray<TextStyle>) = 
            let mutable styleStr = "textStyle={"
            for i = 0 to txtStyle.Count-1 do
                styleStr <- styleStr + "TextStyle." + txtStyle.[i].ToString() + ","
            styleStr.TrimEnd([|','|]) + "}"
        
        /// <summary>
        /// Creates string representaion of the graphical primitive Line in a way omc expects it for
        /// the purpose of updating graphical annotations. </summary>
        /// <param name="line"> 
        /// Line object which will be represented as a string. </param>
        /// <returns>
        /// String representation of the Line object. </returns>
        static member private graphLineToString(line:Line) = 
            let visibleStr = "visible=" + line.Visible.ToString().ToLower()
            let pointsStr = Core.pointsToString(line.Points)
            let colorStr = "color=" + Core.getColorStr( line.Color )
            //let linePattStr = Core.getLinePatternStr(line.Pattern)
            let linePattStr = "pattern=LinePattern." + line.Pattern.ToString()
            let thickStr = "thickness=" + line.Thickness.ToString(new CultureInfo(""))
            let arrowStr = Core.getArrowStr(line.Arrow)
            let arrowSizeStr = "arrowSize=" + line.ArrowSize.ToString(new CultureInfo(""))
            let smoothStr = Core.getSmoothStr(line.Smooth);
            "Line(" + visibleStr + "," + pointsStr + "," + colorStr + "," + linePattStr + "," +
                thickStr + "," + arrowStr + "," + arrowSizeStr + "," + smoothStr + ")" 
                
        /// <summary>
        /// Creates string representaion of the graphical primitive Polygon in a way omc expects it for
        /// the purpose of updating graphical annotations. </summary>
        /// <param name="polygon"> 
        /// Polygon object which will be represented as a string. </param>
        /// <returns>
        /// String representation of the Polygon object. </returns>
        static member private graphPolygonToString(polygon:Polygon) = 
            let visibleStr = "visible=" + polygon.Visible.ToString().ToLower()
            let lineColorStr = "lineColor=" + Core.getColorStr( polygon.LineColor )
            let fillColorStr = "fillColor=" + Core.getColorStr( polygon.FillColor )
            //let linePattStr = Core.getLinePatternStr(polygon.LinePattern)
            let linePattStr = "pattern=LinePattern." +  polygon.Pattern.ToString()
            let fillPattStr = "fillPattern=FillPattern." + polygon.FillPattern.ToString()
            let thickStr = "lineThickness=" + polygon.LineThickness.ToString(new CultureInfo(""))            
            let pointsStr = Core.pointsToString(polygon.Points)                                                
            let smoothStr = Core.getSmoothStr(polygon.Smooth);
            "Polygon(" + visibleStr + "," + lineColorStr + "," + fillColorStr + "," + linePattStr + "," +
                fillPattStr + "," + thickStr + "," + pointsStr + "," + smoothStr + ")" 
        
        /// <summary>
        /// Creates string representaion of the graphical primitive Rectangle in a way omc expects it for
        /// the purpose of updating graphical annotations. </summary>
        /// <param name="rectangle"> 
        /// Rectangle object which will be represented as a string. </param>
        /// <returns>
        /// String representation of the Rectangle object. </returns>  
        static member private graphRectangleToString(rectangle:Rectangle) = 
            let visibleStr = "visible=" + rectangle.Visible.ToString().ToLower()
            let lineColorStr = "lineColor=" + Core.getColorStr( rectangle.LineColor )
            let fillColorStr = "fillColor=" + Core.getColorStr( rectangle.FillColor )
            //let linePattStr = Core.getLinePatternStr(rectangle.LinePattern)
            //let fillPattStr = Core.getFillPatternStr(rectangle.FillPattern)
            let linePattStr =  "pattern=LinePattern." + rectangle.Pattern.ToString()
            let fillPattStr = "fillPattern=FillPattern." + rectangle.FillPattern.ToString()
            let thickStr = "lineThickness=" + rectangle.LineThickness.ToString(new CultureInfo(""))            
            let borderPattStr = "borderPattern=BorderPattern." + rectangle.BorderPattern.ToString()
            let extentStr = Core.extentToString(rectangle.Extent)
            let radiusStr = "radius=" + rectangle.Radius.ToString(new CultureInfo(""));            
            "Rectangle(" + visibleStr + "," + lineColorStr + "," + fillColorStr + "," + linePattStr + "," +
                fillPattStr + "," + thickStr + "," + borderPattStr + "," + extentStr + "," + radiusStr + ")" 
        
        /// <summary>
        /// Creates string representaion of the graphical primitive Ellipse in a way omc expects it for
        /// the purpose of updating graphical annotations. </summary>
        /// <param name="ellipse"> 
        /// Ellipse object which will be represented as a string. </param>
        /// <returns>
        /// String representation of the Ellipse object. </returns>
        static member private graphEllipseToString(ellipse:Ellipse) = 
            let visibleStr = "visible=" + ellipse.Visible.ToString().ToLower()
            let lineColorStr = "lineColor="  + Core.getColorStr( ellipse.LineColor)
            let fillColorStr = "fillColor="  + Core.getColorStr( ellipse.FillColor)
            //let linePattStr = Core.getLinePatternStr(rectangle.LinePattern)
            //let fillPattStr = Core.getFillPatternStr(rectangle.FillPattern)
            let linePattStr = "pattern=LinePattern." +  ellipse.Pattern.ToString()
            let fillPattStr = "fillPattern=FillPattern." + ellipse.FillPattern.ToString()
            let thickStr = "lineThickness=" + ellipse.LineThickness.ToString(new CultureInfo(""))                        
            let extentStr = Core.extentToString(ellipse.Extent)            
            "Ellipse(" + visibleStr + "," + lineColorStr + "," + fillColorStr + "," + linePattStr + "," +
                fillPattStr + "," + thickStr + "," + extentStr + ")" 
        
        /// <summary>
        /// Creates string representaion of the graphical primitive Text in a way omc expects it for
        /// the purpose of updating graphical annotations. </summary>
        /// <param name="text"> 
        /// Text object which will be represented as a string. </param>
        /// <returns>
        /// String representation of the Text object. </returns>
        static member private graphTextToString(text:Text) = 
            let visibleStr = "visible=" + text.Visible.ToString().ToLower()
            let lineColorStr = "lineColor="  + Core.getColorStr( text.LineColor)
            let fillColorStr = "fillColor="  + Core.getColorStr( text.FillColor)
            //let linePattStr = Core.getLinePatternStr(text.LinePattern)
            //let fillPattStr = Core.getFillPatternStr(text.FillPattern)
            let linePattStr =  "pattern=LinePattern." + text.Pattern.ToString()
            let fillPattStr = "fillPattern=FillPattern." + text.FillPattern.ToString()
            let thickStr = "lineThickness=" + text.LineThickness.ToString(new CultureInfo(""))                        
            let extentStr = Core.extentToString(text.Extent)
            let textStr = "textString=\"" + text.TextString + "\""
            let fontSizeStr = "fontSize=" + text.FontSize.ToString(new CultureInfo(""))
            let fontNameStr = "fontName=\"" + text.FontName + "\""
            // TODO: omc seems not to support text styles yet...
            //let textStyleStr = Core.getTextStyleStr(text.TextStyle)
            "Text(" + visibleStr + "," + lineColorStr + "," + fillColorStr + "," + linePattStr + "," +
                fillPattStr + "," + thickStr + "," + extentStr + "," + textStr + ","+ fontSizeStr + "," + fontNameStr 
                //+ ","  + textStyleStr 
                + ")"
        /// <summary>
        /// Creates string representaion of the graphical primitive Bitmap in a way omc expects it for
        /// the purpose of updating graphical annotations. </summary>
        /// <param name="bitmap"> 
        /// Bitmap object which will be represented as a string. </param>
        /// <returns>
        /// String representation of the Bitmap object. </returns>    
        static member private graphBitmapToString(bitmap:Bitmap) = 
            let visibleStr = "visible=" + bitmap.Visible.ToString().ToLower()
            let extentStr = Core.extentToString(bitmap.Extent)
            let fileNameStr = "fileName=" + bitmap.FileName
            let imageSrcStr = "imageSource=" + bitmap.ImageSource
            "Bitmap(" + visibleStr + "," + extentStr + "," + fileNameStr + "," + imageSrcStr + ")"
        
        /// <summary>
        /// Creates string representaion of the graphical primitive in a way omc expects it for
        /// the purpose of updating graphical annotations. Calls appropriate functions for every particular 
        /// of the graphical primitive. Uses string accumulator because it's used in ResizeArray.fold_left</summary>
        /// <param name="acc"> 
        /// String accumulator for graphical primitives. </param>
        /// <param name="item"> 
        /// Graphical item string represenation of which should be obtained. </param>
        /// <returns>
        /// String representation of the graphical primitives the icon consists of. </returns>    
        static member private graphicPrimitiveToString (acc:string) (item:GraphicItem) = 
            let primitiveStr =  
                match item with
                    | :? Line -> Core.graphLineToString(item :?> Line)
                    | :? Polygon -> Core.graphPolygonToString(item :?> Polygon)
                    | :? Rectangle -> Core.graphRectangleToString(item :?> Rectangle)
                    | :? Ellipse -> Core.graphEllipseToString(item :?> Ellipse)
                    | :? Text -> Core.graphTextToString(item :?> Text)
                    | :? Bitmap -> Core.graphBitmapToString(item :?> Bitmap)
                    | _ -> raise (Exception("Unknown graphic primitive"))
            acc + primitiveStr + ","
        
        /// <summary>
        /// Creates string representaion of the Extent obejct in a way omc expects it. </summary>
        /// <param name="ext"> 
        /// Extent object which will be represented as a string. </param>
        /// <returns>
        /// String representation of the Extent object. </returns>
        static member private extentToString(ext:Extent) = 
             "extent={{" + ext.P1.X.ToString(new CultureInfo("")) + "," + ext.P1.Y.ToString(new CultureInfo("")) + "},{" +
                ext.P2.X.ToString(new CultureInfo("")) + "," + ext.P2.Y.ToString(new CultureInfo("")) + "}}"
        
        /// <summary>
        /// Updates the represenation of the icon on the omc. </summary>
        /// <param name="mdClass"> 
        /// ModelicaClass icon of which should be updated. </param>        
        static member private updateIcon(mdClass:ModelicaClass) =             
            let primitivesStr = ( mdClass.Icon.Graphics |> ResizeArray.fold_left Core.graphicPrimitiveToString "graphics={" ).TrimEnd([|','|]) + "}"
            let coordSystem = "coordinateSystem=CoordinateSystem(" + Core.extentToString(mdClass.Icon.CoordinateSystem.Extent) + ")"
            let annotString = "annotate=Icon(" + coordSystem + "," + primitivesStr + ")"
            omc.AddClassAnnotation(mdClass.QualifiedName + "," + annotString)
                            
        /// <summary>
        /// Updates the icon anotation on the server side (in OMC). This includes the icon itself and
        /// placement of all connectors </summary>
        /// <param name="mdClass" >
        /// Qualified name of the class whose icon should be updated.</param>
        /// <returns>
        /// Return value should be ignored, it's likely to be removed in future releases. </returns>
        static member UpdateClassIcon(mdClass:ModelicaClass) = 
            // foreach component update placement
            mdClass.Components |> ResizeArray.map Core.updateComponentPlacement            
            // update the icon of the class
            Core.updateIcon(mdClass)
            
        /// <summary>    
        /// Helper function for ModelToString </summary>
        static member private modelToStringList(model:ModelicaClass) =
            let desc:ResizeArray<string> = model.ContainedClasses |> ResizeArray.map Core.ModelToString            
            desc.Insert(0,model.ToString() )
            desc
        
        /// <summary>
        /// Creates string containing flat view of model. Just for testing purposes. </param>
        /// <param name="model">
        /// Root class of view of the model </param>
        /// <returns>
        /// String with class types and names within the model </returns>
        static member ModelToString(model:ModelicaClass) =
            let modelStrArray = Core.modelToStringList(model)
            String.Concat(  (modelStrArray |> ResizeArray.map( fun(a:string) -> a+ System.Environment.NewLine ) ).ToArray() )
            //String.Concat( modelStrArray.ToArray() )